#include "makecard_bitmap.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>

void InitCardParam(PRINT_CARD_PARAM &JobPara)
{
	JobPara.dwSize = sizeof(PRINT_CARD_PARAM);

	//all the BITMAP has 648 pixels width and 1012 pixels height and 24-bits per pixels
	//if the data pointer is null, than the plane will not be printed.
	JobPara.lpFrontBGR		= nullptr;
	JobPara.lpFrontK		= nullptr;
	JobPara.lpFrontO		= nullptr;
	JobPara.lpBackBGR		= nullptr;
	JobPara.lpBackK			= nullptr;
	JobPara.lpBackO			= nullptr;

	//Heating Energy adjustment, value range of following fields are -127 ~ 127
	//same as driver UI Heating Energy tab
	//for ribbon YMCKO
	JobPara.chFrontHeatYMC		= 0;
	JobPara.chFrontHeatK		= 0;
	JobPara.chFrontHeatO		= 0;

	JobPara.chBackHeatYMC		= 0;
	JobPara.chBackHeatK			= 0;
	JobPara.chBackHeatO			= 0;

	//for ribbon K
	JobPara.chFrontHeatResinK	= 0;
	JobPara.chBackHeatResinK	= 0;
}

#define  FREE_BITMAP_PARAM(bmp) do {\
    if(bmp) {\
        if (bmp->bmBits){\
            delete [] (uint8_t*)bmp->bmBits;\
            bmp->bmBits = nullptr;\
        }\
    }\
}while(0)

void FreeCardParam(PRINT_CARD_PARAM &JobPara)
{
    FREE_BITMAP_PARAM(JobPara.lpFrontBGR);
    FREE_BITMAP_PARAM(JobPara.lpFrontK);
    FREE_BITMAP_PARAM(JobPara.lpFrontO);
    FREE_BITMAP_PARAM(JobPara.lpBackBGR);
    FREE_BITMAP_PARAM(JobPara.lpBackK);
    FREE_BITMAP_PARAM(JobPara.lpBackO);
}

uint32_t  ReadBmpFile(char* szFileName, BITMAP* lpBmp)
{
	BITMAPFILEHEADER	BmpFileHdr = {0};
	BITMAPINFOHEADER	BmpInfoHdr = {0};
	RGBQUAD				IndexColors[256] = {{0}};
	uint32_t			dwRead = 0;
	bool				bRet = true;
	int32_t				nChannel = 3,
						nBitCount = 0,
						nRet = 0;

	uint32_t			dwReadOneTime = 0,
						dwTotal = 0;
	uint8_t				*lpTmp = 0,
						*lpTop = 0,
						*lpBottom = 0;
	uint32_t			i = 0;
	uint32_t			nHeight = 0;
	uint8_t				byValue = 0;

	FILE				*fp = 0;
	uint8_t				lpBuf[64] = {0};

	(void)bRet;

	if (lpBmp == 0 )
		return 87;//ERROR_INVALID_PARAMETER;

	if ( szFileName[0] == 0 )
		return 87;//ERROR_INVALID_PARAMETER;

	fp = fopen(szFileName, "rb");

	if ( fp == 0 )
		return 110;//ERROR_OPEN_FAILED

	nRet = fseek(fp, 0, SEEK_SET);

	//dwRead = fread((void*)&BmpFileHdr, 1, sizeof(BITMAPFILEHEADER), fp);
	dwRead = fread(lpBuf, 1, 14, fp);
	BmpFileHdr.bfType		= MAKEWORD(lpBuf[0], lpBuf[1]);
	BmpFileHdr.bfSize		= MAKELONG(MAKEWORD(lpBuf[2], lpBuf[3]), MAKEWORD(lpBuf[4], lpBuf[5]));
	BmpFileHdr.bfReserved1	= MAKEWORD(lpBuf[6], lpBuf[7]);
	BmpFileHdr.bfReserved1	= MAKEWORD(lpBuf[8], lpBuf[9]);
	BmpFileHdr.bfOffBits	= MAKELONG(MAKEWORD(lpBuf[10], lpBuf[11]), MAKEWORD(lpBuf[12], lpBuf[13]));

	dwRead = fread((void*)&BmpInfoHdr, 1, sizeof(BITMAPINFOHEADER), fp);

	nBitCount = BmpInfoHdr.biPlanes * BmpInfoHdr.biBitCount;
	if ( nBitCount != 8 && nBitCount != 24 )
	{
		nRet = fclose(fp);
		return 50;//=ERROR_NOT_SUPPORTED;
	}

	if ( nBitCount == 8 )
		dwRead = fread((void*)IndexColors, 1, sizeof(RGBQUAD)*256, fp);

	nChannel = BmpInfoHdr.biBitCount / 8;

	lpBmp->bmType		= 0;
	lpBmp->bmWidth		= BmpInfoHdr.biWidth;
	lpBmp->bmHeight		= BmpInfoHdr.biHeight;
	lpBmp->bmWidthBytes	= ((BmpInfoHdr.biWidth*nChannel+3)/4*4);
	lpBmp->bmPlanes		= BmpInfoHdr.biPlanes;
	lpBmp->bmBitsPixel	= BmpInfoHdr.biBitCount;

	dwTotal = lpBmp->bmWidthBytes * lpBmp->bmHeight;
	lpBmp->bmBits		= (void*)new char[dwTotal];

	nRet = fseek(fp, BmpFileHdr.bfOffBits, SEEK_SET);

	dwReadOneTime = 1 * 1024 * 1024;
	lpTmp = (uint8_t*)lpBmp->bmBits;

	while ( dwTotal > 0 )
	{
		if ( dwTotal >= dwReadOneTime )
		{
			dwRead = fread((void*)lpTmp, 1, dwReadOneTime, fp);

			dwTotal -= dwReadOneTime;
			lpTmp += dwReadOneTime;
		}
		else
		{
			dwRead = fread((void*)lpTmp, 1, dwTotal, fp);
			dwTotal = 0;
		}
	}

	fclose(fp);

	if ( nBitCount == 8 )
	{
		dwTotal = lpBmp->bmWidthBytes * lpBmp->bmHeight;
		lpTmp = (uint8_t*)lpBmp->bmBits;
		for(i=0;i<dwTotal;i++,lpTmp++)
		{
			byValue = *lpTmp;
			*lpTmp = IndexColors[byValue].rgbBlue;
		}
	}


	dwTotal = (uint32_t)lpBmp->bmWidthBytes;
	nHeight = lpBmp->bmHeight / 2;

	lpTmp = new uint8_t[dwTotal];
	lpTop = (uint8_t*)lpBmp->bmBits;
	lpBottom = (uint8_t*)lpBmp->bmBits + lpBmp->bmWidthBytes * (lpBmp->bmHeight-1);

	for(i=0;i<nHeight;i++)
	{
		memcpy(lpTmp, lpTop, dwTotal);
		memcpy(lpTop, lpBottom, dwTotal);
		memcpy(lpBottom, lpTmp, dwTotal);

		lpTop += dwTotal;
		lpBottom -= dwTotal;
	}

	delete [] lpTmp;

	return 0;
}